package org.zhang.learn

// 可以在顶层申明变量
const val PI = 3.14

fun main(args: Array<String>) {
    println("PI = $PI")
    intFormatUse()
    printSum(5, 6)
    valVariable()
    varVariable()
    useRectangle()
    strTemplate()
    conditionExpress(5, 6)
    ifKeyWordUesAsExpress(5, 6)
    forExpress()
    whileExpress()
    whenExpress()
    rangeUsage()
}

/**
 * 整数的定义：为了整数的可读性可以用_作为分隔符，但是_不能用在数字的结尾处。
 */
fun intFormatUse() {
    val a: Int = 12_450;
    println("a = $a")
}

/**
 * 学习函数的创建
 * 这是一个函数
 */
fun sum(a: Int, b: Int): Int {
    return a + b
}

/**
 * 返回无意义的值的函数
 * 相当于java当中返回void的返回值的函数
 * Unit 可以省略
 */
fun printSum(a: Int, b: Int): Unit {
    println("$a + $b = ${a + b}")
}

/**
 * 定义只读局部变量使用关键字 val 定义。只能为其赋值一次。
 */
fun valVariable() {
    //sampleStart
    val a: Int = 1  // 立即赋值
    val b = 2       // 自动推断出 `Int` 类型
    val c: Int      // 如果没有初始值类型不能省略
    c = 3           // 明确赋值
    //sampleEnd
    println("a = $a, b = $b, c = $c")
}

/**
 * 可重新赋值的变量使用 var 关键字。
 */
fun varVariable() {
    //sampleStart
    var x = 5 // 自动推断出 `Int` 类型
    x += 1
    //sampleEnd
    println("x = $x")
}

/**
 * 使用 class 关键字定义类。
 * 默认情况下类都是 final 的；如需让一个类可继承， 请将其标记为 open。
 */
open class Shape

/**
 * 类的属性可以在其声明或主体中列出。
 * 类之间继承由冒号（:）声明。
 */
class Rectangle(height: Double, length: Double) : Shape() {
    var perimeter = (height + length) * 2
}

/**
 * 具有类声明中所列参数的默认构造函数会自动可用。
 */
fun useRectangle() {
    var rectangle = Rectangle(5.0, 2.0)
    println(rectangle.perimeter)
}

/**
 * 注释的使用
 * Kotlin编程语言中注释可以嵌套注释
 */
fun commons() {
    // 这是单行注释

    /*
    这是多行注释
     */

    /* 注释从这里开始
    /* 包含嵌套的注释 *&#8288;/
    并且在这里结束。 */
     */
}

/**
 * 字符串模板
 */
fun strTemplate() {
    var a = 1
    // 模板中的简单名称
    val s1 = "a is $a"

    a = 2/**/
    // 在模板中使用表达式
    val s2 = "${s1.replace("is", "was")}, but now is $a"

    println(s2)
}

/**
 * 条件表达式的使用
 */
fun conditionExpress(a: Int, b: Int): Int {
    if (a > b) {
        return a
    } else {
        return b
    }
}

/**
 * 在 Kotlin 中，if 也可以用作表达式。
 */
fun ifKeyWordUesAsExpress(a: Int, b: Int): Int = if (a > b) a else b

/**
 * for 循环
 */
fun forExpress() {
    val items = listOf("apple", "banana", "kiwifruit")
    for (item in items) {
        println(item)
    }

    // 或者
    for (index in items.indices) {
        println("item at $index is ${items[index]}")
    }
}

/**
 * while 循环
 */
fun whileExpress() {
    val items = listOf("apple", "banana", "kiwifruit")
    var index = 0;
    while (index < items.size) {
        println("item at $index is ${items[index]}")
        index++
    }
}

/**
 * when express and use
 */
fun whenExpress() {
    println("\n")
    println("----- when express and usage -----")
    val items = listOf(1, "hello", 1000L, 2, "other")
    for (item in items) {
        println(
            when (item) {
                1 -> "one"
                "hello" -> "Greeting"
                is Long -> "Long"
                !is String -> "not a String"
                else -> "Unknow"
            }
        )
    }
}

/**
 * range usage
 */
fun rangeUsage() {
    println("\n")
    println("----- range usage -----")
    // 使用 in 操作符来检测某个数字是否在指定区间内。
    val x = 10
    val y = 9
    if (x in 1..y + 1) {
        println("fit in range")
    }

    // 检测某个数字是否在指定区间外。
    // list.indices 返回的是一个range对象
    val list = listOf("a", "b", "c")
    if (-1 !in 0..list.lastIndex) {
        println("-1 is out of range")
    }
    if (list.size !in list.indices) {
        println("list size is out of valid list indices range, too")
    }

    // 迭代区间
    for (x in 1..5) {
        print(x)
    }

    // 数列迭代
    for (x in 1..10 step 2) {
        print(x)
    }
    println()
    for (x in 9 downTo 0 step 3) {
        print(x)
    }
}

